home *** CD-ROM | disk | FTP | other *** search
/ ASME's Mechanical Engine…ing Toolkit 1997 December / ASME's Mechanical Engineering Toolkit 1997 December.iso / edu_comp / tpnovell.lzh / CIS.PAS
Pascal/Delphi Source File  |  1987-10-02  |  20KB  |  530 lines

  1. { This is my Novell Toolbox for printing, file and record locking, }
  2. { logical locks, and semaphores. }
  3.  
  4. { If you use these routines in your software, and find them of value, }
  5. { please send a contribution of $15 to $50 to me for funding of additional }
  6. { toolboxes.  If you find these routines useful and use them in a commercial }
  7. { application, no royalties are requested.  If you do profit from these }
  8. { routines, please consider a larger donation. }
  9.  
  10. { Also please send your ideas for future toolboxes.  The current plans }
  11. { include Novell spooling print functions, an IPX concentrator, and of }
  12. { course, the elusive Novell B+ Tree routines, compatible with Borland's }
  13. { database toolbox, but completely networkable.  I know you want these, and }
  14. { if I find time, I'll finish them.  Your contributions go a long way towards }
  15. { finding the time to work on this stuff. }
  16. { Telephone support is available for my routines at Micro Networks of America }
  17. { in Farmington, CT (203) 678-7400.  Our current consulting rate must be }
  18. { charged if I support you from the office, via the phone.  Other support is }
  19. { available for free via compuserve (Borland SIG) or via mail at home. }
  20. {  The address for contributions and support questions is: }
  21. {              Scott A. Lewis
  22.                36 Maythorpe Drive
  23.                Windsor, CT 06095
  24.  
  25. On Compuserve, send mail to 76515,135 via Easyplex or Borland's SIG.
  26.  
  27. }
  28.  
  29. { The future toolboxes complete descriptions are as follows:
  30.  
  31.     IPX concentrator:  A PC to PC communications toolbox using Novell's
  32.                        IPX internetwork communications.  The primary
  33.                        application will be sharing a host communication
  34.                        line, however, a print or modem server might be
  35.                        easily implemented.
  36.  
  37.      Novell print spooling:  A demo program that is a simple popup spool
  38.                              utility.  Similar to Hotprint, but with less
  39.                              complexity.  The toolbox will include functions
  40.                              for all of Novell's printing function calls.
  41.  
  42.      Novell B+ Trees:  I needn't explain this one, especially if you have
  43.                        followed my LAN threads on Compuserve (Borland SIG).
  44.                        I really have been working on this one, but it is big,
  45.                        tough to document, and difficult to make as fast as the
  46.                        original.  I'll get one of these days.
  47.  
  48. Send your ideas for future toolboxes !
  49.  
  50. }
  51.  
  52. TYPE
  53.   Str80 = STRING[80];
  54.   RecLogType = STRING[100];
  55.   Str6 = STRING[6];
  56.   BigStr = STRING[255];
  57.   Reg_Type = RECORD
  58.                CASE Byte OF
  59.                  0 : (AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags : Integer);
  60.                  1 : (AL, AH, BL, BH, CL, CH, DL, DH : Byte);
  61.              END;
  62.   Request_Type = ARRAY[1..7] OF Byte;
  63.   Reply_Type = ARRAY[1..90] OF Char;
  64.  
  65. VAR
  66.   Regs : Reg_Type;
  67.   Request_Buff : Request_Type;
  68.   Reply_Buff : Reply_Type;
  69.   I, J : Integer;
  70.  
  71.   FUNCTION Open_Semaphore(Sem : BigStr;
  72.                           InitVal : Integer;
  73.                           VAR SemHandle1 : Integer;
  74.                           VAR SemHandle2 : Integer;
  75.                           VAR Num_Using : Integer) : Boolean;
  76. { Semaphores are used for exclusion when record locking is not appropriate }
  77. { The value is set the first time the semaphore is opened, thereafter you }
  78. { must use wait semaphore or signal semaphore to change the value }
  79.   BEGIN
  80.     WITH Regs DO
  81.       BEGIN
  82.         IF (Sem[0] > #127) OR (InitVal < 0) OR (InitVal > 127) THEN
  83.           BEGIN                        { Semaphore must not exceed 127 chars }
  84.             Open_Semaphore := False;     { InitVal must be between 0 and 127 }
  85.             Exit;
  86.           END;
  87.         AH := $C5;                                      { Semaphore function }
  88.         AL := $0;                                    { Sub-Function 0 = open }
  89.         DS := Seg(Sem);                               { DS:DX points to name }
  90.         DX := Ofs(Sem);                             { Byte 0 = length 0..127 }
  91.         CL := InitVal;                                { Initial Value 0..127 }
  92.  
  93.         MsDos(Regs);                                    { Give it to Int 21h }
  94.  
  95.         Num_Using := BL;              { Number of users using this semaphore }
  96.         Open_Semaphore := (AL = 0);               { OK if AL comes back as 0 }
  97.         SemHandle1 := CX;                 { CX:DX holds the semaphore handle }
  98.         SemHandle2 := DX;
  99.       END;                                                    { with Regs do }
  100.   END;                                              {Function Open_Semaphore }
  101.  
  102.  
  103.   FUNCTION Examine_Semaphore(SemHandle1, SemHandle2 : Integer;
  104.                              VAR Value : Integer;
  105.                              VAR Num_Using : Integer) : Boolean;
  106. { The semaphore value that comes back in CL is the count from the open call }
  107. { DL represents the current open count - the open count is incremented }
  108. { anytime  a station opens the semaphore this can be used for controlling }
  109. { the number of users using your software }
  110.  
  111.   BEGIN
  112.     WITH Regs DO
  113.       BEGIN
  114.         AH := $C5;                                 { Semaphore function call }
  115.         AL := 1;                                  { Sub-Function 1 = examine }
  116.         CX := SemHandle1;
  117.         DX := SemHandle2;
  118.  
  119.         MsDos(Regs);                                        { Give it to DOS }
  120.  
  121.         Value := CX;                                 { Semaphore value in CX }
  122.         Num_Using := DL;                       { Number using this semaphore }
  123.         Examine_Semaphore := (AL = 0);                     { AL = 0 means OK }
  124.       END;
  125.   END;                                          { function Examine_Semaphore }
  126.  
  127.   FUNCTION Wait_Semaphore(SemHandle1, SemHandle2 : Integer;
  128.                           Wait_Time : Integer) : Boolean;
  129. { Decrement the semaphore value and wait if it is negative.  If negative, }
  130. { the workstation will wait until it becomes non-negative or until a }
  131. { timeout occurs. }
  132.  
  133.   BEGIN
  134.     WITH Regs DO
  135.       BEGIN
  136.         AH := $C5;                                 { Semaphore function call }
  137.         AL := 2;                                     { Sub-Function 2 = wait }
  138.         BP := Wait_Time;                      { In 1/18 seconds, 0 = No wait }
  139.         CX := SemHandle1;
  140.         DX := SemHandle2;
  141.  
  142.         MsDos(Regs);                                        { Give it to DOS }
  143.  
  144.         Wait_Semaphore := (AL = 0);        { AL = 0 means OK, else timeout or 
  145.                                                               Invalid handle }
  146.       END;
  147.   END;                                             { function Wait_Semaphore }
  148.  
  149.   FUNCTION Signal_Semaphore(SemHandle1, SemHandle2 : Integer) : Boolean;
  150.  
  151. { Increment the semaphore value and release if waiting.  If any stations }
  152. { are waiting, the station that has been waiting the longest will be }
  153. { signalled to proceed }
  154.  
  155.   BEGIN
  156.     WITH Regs DO
  157.       BEGIN
  158.         AH := $C5;                                 { Semaphore function call }
  159.         AL := 3;                                   { Sub-Function 3 = signal }
  160.         CX := SemHandle1;
  161.         DX := SemHandle2;
  162.  
  163.         MsDos(Regs);                                        { Give it to DOS }
  164.  
  165.         Signal_Semaphore := (AL = 0);      { AL = 0 means OK, else overflow ( value > 128 ) }
  166.                                            { or Invalid handle }
  167.       END;
  168.   END;                                           { function Signal_Semaphore }
  169.  
  170.   FUNCTION Close_Semaphore(SemHandle1, SemHandle2 : Integer) : Boolean;
  171.  
  172. { Decrement the open count of a semaphore.  When the open count goes }
  173. { to zero, the semaphore is destroyed. }
  174.  
  175.   BEGIN
  176.     WITH Regs DO
  177.       BEGIN
  178.         AH := $C5;                                 { Semaphore function call }
  179.         AL := 4;                                    { Sub-Function 4 = close }
  180.         CX := SemHandle1;
  181.         DX := SemHandle2;
  182.  
  183.         MsDos(Regs);                                        { Give it to DOS }
  184.  
  185.         Close_Semaphore := (AL = 0);  { AL = 0 means OK, else Invalid handle }
  186.       END;
  187.   END;                                            { function Close_Semaphore }
  188.  
  189.   FUNCTION Set_Lock_Mode : boolean;
  190. { Note that if other applications are running that were written for Netware }
  191. { 4.61 or older, this should be set back to old compatibility mode before we }
  192. { exit.   This can be done by using this call with AL = 00h }
  193.   BEGIN
  194.     WITH Regs DO
  195.       BEGIN
  196.         AH := $C6;                                      { Lock mode function }
  197.         AL := 1;                                     { We want extended mode }
  198.       END;
  199.   END;
  200.  
  201. (* THE FOLLOWING PROCEDURES ARE FOR LOGGING AND LOCKING/RELEASING FILE SETS *)
  202. (* File locking by set can be very effective in avoiding deadly embrace *)
  203.  
  204.   FUNCTION Lock_File_Set(Mode : Byte; Timeout : Byte) : Boolean;
  205. { Lock a set of files that were logged by function $EB log asciiz file }
  206.   BEGIN
  207.     WITH Regs DO
  208.       BEGIN
  209.         AH := $CB;                                  { Lock File Set Function }
  210.         DL := Mode;                                  { 0 = No Wait, 1 = wait }
  211.         BP := Timeout;                     { in 1/18 seconds ... 0 = No Wait }
  212.  
  213.         MsDos(Regs);                                        { Give it to DOS }
  214.  
  215.         Lock_File_Set := (AL = 0);  { Al = 0 means OK FF = Fail FE = Timeout }
  216.       END;
  217.  
  218.   END;                 { function Lock_File_Set(Mode : Byte; Timeout : Byte) }
  219.  
  220. Procedure Release_File_Set;
  221. { Release lock on set of files in logged table, files remain logged }
  222. { These files remain open but cannot be accessed without an error }
  223. { To reuse them, send another lock file set }
  224.   BEGIN
  225.     WITH Regs DO
  226.       BEGIN
  227.         AH := $CD;                               { Release file set function }
  228.         MsDos(Regs);
  229.       END;
  230.   END;                                          { function Release_File_Set  }
  231.  
  232. FUNCTION Clear_File_Set : Boolean;
  233. { Unlock and UnLog the entire personal file set (all files are closed) }
  234.   BEGIN
  235.     WITH Regs DO
  236.       BEGIN
  237.         AH := $CF;                               { Release File Set Function }
  238.         MsDos(Regs);
  239.         Clear_File_Set := (AL = 0);  { Al = 0 means OK }
  240.       END;
  241.   END;                                             { function Clear_File_Set }
  242.  
  243.   FUNCTION Log_File(FName : Str80; Mode : Byte; Timeout : Byte) : Boolean;
  244.   VAR
  245.     Asciiz : STRING[80];
  246. { This function allows a station to log files fro later personal use }
  247. { After the desired files are logged, function CBh can be used to lock }
  248. { the entire set of files }
  249.   BEGIN
  250.     WITH Regs DO
  251.       BEGIN
  252.         AH := $EB;                              { Log Asciiz string function }
  253.         AL := Mode;                           { 0 = Log Only, 1 Log and Lock }
  254.         BP := Timeout;                        { in 1/18 seconds, 0 = No wait }
  255.         Asciiz := FName+#0;                { Terminate with a nul for asciiz }
  256.         DS := Seg(Asciiz);
  257.         DX := Ofs(Asciiz[1]);
  258.  
  259.         MsDos(Regs);
  260.  
  261.         Log_File := (AL = 0);
  262.       END;
  263.   END;                                                   { function Log_File }
  264.  
  265.   FUNCTION Release_File(FName : Str80) : boolean;
  266.   VAR
  267.     Asciiz : STRING[80];
  268. { Release file lock, but keep logged in the table }
  269.   BEGIN
  270.     WITH Regs DO
  271.       BEGIN
  272.         AH := $EC;                                       { Release file call }
  273.         Asciiz := FName+#0;                                 { null terminate }
  274.         DS := Seg(Asciiz);
  275.         DX := Ofs(Asciiz[1]);
  276.  
  277.         MsDos(Regs);
  278.       END;
  279.   END;                                               { function Release_File }
  280.  
  281.   FUNCTION Clear_File(FName : Str80) : boolean;
  282.   VAR
  283.     Asciiz : STRING[80];
  284. { Release a file from the file log table, unlock the file if it is locked }
  285.   BEGIN
  286.     WITH Regs DO
  287.       BEGIN
  288.         AH := $ED;
  289.         Asciiz := FName+#0;
  290.         DS := Seg(Asciiz);
  291.         DX := Ofs(Asciiz[1]);
  292.         MsDos(Regs);
  293.         Clear_File := (AL = 0);  { Al = 0 means OK }
  294.       END;
  295.   END;                                                 { Function Clear_File }
  296.  
  297.  
  298. (* THE FOLLOWING FUNCTIONS ARE FOR LOGICAL LOCKING OPERATIONS *)
  299. (* Logical locks work only if all software accessing the files use the *)
  300. (* same logical synchronization scheme.  Logical locks are much easier *)
  301. (* and faster to implement than physical locks. *)
  302.  
  303.  
  304.   FUNCTION Begin_Logical_Locking(Mode, Timeout : Integer) : Boolean;
  305.  
  306. { Call this when you are about to start the read modify update cycle on an }
  307. { open shareable file or set of files.  The mode can be zero or one for }
  308. { No wait or wait, if wait is chosen, the timeout value is set in 1/18th }
  309. { seconds.  When the shell receives this call, it sends a request to the }
  310. { server to lock all shareable files that the workstation has opened.  This }
  311. { only works on file flagged as shareable and is only effective if all }
  312. { stations that are acessing the files use this method }
  313.  
  314.   BEGIN
  315.     WITH Regs DO
  316.       BEGIN
  317.         AH := $C8;                     { Begin Logical File Locking Function }
  318.         DL := Mode;                                  { 0 = No wait, 1 = Wait }
  319.         IF Mode = 1 THEN
  320.           BP := Timeout;          { timeout in 1/18th seconds -- 0 = No wait }
  321.         MsDos(Regs);
  322.         Begin_Logical_Locking := (AL = 0);        { AL=FFh if fail, AL=FEh if
  323.                                                                      timeout }
  324.       END;
  325.   END;                                      { function Begin_Logical_Locking }
  326.  
  327. FUNCTION End_Logical_Locking : Boolean;
  328. { This call will indicate that the read modify update cycle is complete }
  329. { and unlock the logical locks previously placed by Begin_Logical_Locking }
  330.  
  331.   BEGIN
  332.     WITH Regs DO
  333.       BEGIN
  334.         AH := $C9;
  335.         MsDos(Regs);
  336.         End_Logical_Locking := (AL = 0);
  337.       END;
  338.   END;                                                 { End_Logical_Locking }
  339.  
  340. FUNCTION Log_Logical_Record(Flg, Timeout : Integer; VAR RecName : RecLogType) : Boolean;
  341.  
  342. { This function will log the specified record string in the record log table }
  343. { of the requesting station.  The record format for this string is as follows }
  344.  
  345.     {    byte      value  }
  346.     {    0         length }
  347.     {    1..100    data   }
  348.  
  349.   BEGIN
  350.     WITH Regs DO
  351.       BEGIN
  352.         AH := $D0;
  353.         AL := Flg;     { If bit zero is set, lock as well as log }
  354.                        { If bit one is set, non-exclusive lock( valid only if }
  355.                        { bit zero is set. }
  356.         DS := Seg(RecName);
  357.         DX := Ofs(RecName);
  358.         BP := Timeout;       { In 1/18th seconds (use only with lock bit set }
  359.  
  360.         MsDos(Regs);
  361.  
  362.         Log_Logical_Record := (AL = 0);          { Possible errors in AL are }
  363.         { AL=FFh  fail }
  364.         { AL=FEh  timeout }
  365.         { AL=96h  No dynamic memory for file }
  366.       END;
  367.   END;                                                  { Log_Logical_Record }
  368.  
  369.   FUNCTION Lock_Logical_RecSet(Timeout : Integer) : Boolean;
  370.  
  371. { Call this to lock all records logged with Log_Logical_Record }
  372.  
  373.   BEGIN
  374.     WITH Regs DO
  375.       BEGIN
  376.         AH := $D1;
  377.         BP := Timeout;                      { In 1/18th seconds, 0 = No wait }
  378.         MsDos(Regs);
  379.         Lock_Logical_RecSet := (AL = 0);    { AL=FF - fail,  AL=FE - timeout }
  380.       END;
  381.   END;                                                 { Lock_Logical_RecSet }
  382.  
  383.   FUNCTION Release_Logical_Rec(VAR RecName : RecLogType) : Boolean;
  384.  
  385. { Call this to release a logical record lock without removing the rec }
  386. { from the table }
  387.  
  388.   BEGIN
  389.     WITH Regs DO
  390.       BEGIN
  391.         AH := $D2;
  392.         DS := Seg(RecName);
  393.         DX := Ofs(RecName);
  394.         MsDos(RecName);
  395.         Release_Logical_Rec := (AL = 0);
  396.       END;
  397.   END;                                                 { Release_Logical_Rec }
  398.  
  399.   FUNCTION Release_Logical_RecSet : Boolean;
  400. { release all locked logical records, doesn't remove them from the table }
  401.   BEGIN
  402.     WITH Regs DO
  403.       BEGIN
  404.         AH := $D3;
  405.         MsDos(Regs);
  406.         Release_Logical_RecSet := (AL = 0);
  407.       END;
  408.   END;                                              { Release_Logical_RecSet }
  409.  
  410.   FUNCTION Clear_Logical_Rec(VAR RecName : RecLogType) : Boolean;
  411. { This call unlocks and removes the Logical Record lock from the table }
  412.   BEGIN
  413.     WITH Regs DO
  414.       BEGIN
  415.         AH := $D4;
  416.         DS := Seg(RecName);
  417.         DX := Ofs(RecName);
  418.         MsDos(Regs);
  419.         Clear_Logical_Rec := (AL = 0);
  420.       END;
  421.   END;                                                   { Clear_Logical_Rec }
  422.  
  423.   FUNCTION Clear_Logical_RecSet : Boolean;
  424. { Unlocks and removes from the table all of the stations logical record locks }
  425.   BEGIN
  426.     WITH Regs DO
  427.       BEGIN
  428.         AH := $D5;
  429.         MsDos(Regs);
  430.         Clear_Logical_RecSet := (AL = 0);
  431.       END;
  432.   END;                                                { Clear_Logical_RecSet }
  433.  
  434.  
  435.   (* THE FOLLOWING ARE PHYSICAL RECORD LOCK CALLS *)
  436.  
  437.  
  438. function Log_Phys_Rec(flg : byte; Handle,Start_Hi,Start_Lo,TimeOut,Size_Hi,Size_Lo : integer): boolean;
  439. { Flg = bit 0 set means log and lock, bit 1 set means non-exclusive lock }
  440. { Handle is the file handle, Start is the high and low starting word to lock }
  441. { from; Size is the high and low word length to lock to.  Timeout is in }
  442. { 1/18th seconds and is only valid if bit 0 of flg is set. }
  443.  
  444. begin
  445.   with regs do
  446.     begin
  447.       AH := $BC;
  448.       AL := flg;
  449.       BX := Handle;
  450.       CX := Start_hi;
  451.       DX := Start_Lo;
  452.       BP := TimeOut;
  453.       SI := Size_Hi;
  454.       DI := Size_Lo;
  455.  
  456.       MSDOS(Regs);
  457.  
  458.       Log_Phys_Rec := (AL = 0);  { $FF = fail, $96 = No dynamic memory }
  459.     end;  { with }
  460. end; { function Log_Phys_Rec(flg : byte; Handle,Start_Hi,Start_Lo,TimeOut,Size_Hi,Size_Lo : integer) }
  461.  
  462. function Release_Phys_Rec( Handle, Start_Hi, Start_Lo : integer) : boolean;
  463. { When a record is released, it is unlocked for use by someone else, but }
  464. { it remains in the log table }
  465. { Handle is the file handle, Start_Hi and Start_Lo are the boundaries of }
  466. { the locked region to be released }
  467. begin
  468.   with regs do
  469.     begin
  470.       AH := $BD;
  471.       BX := Handle;
  472.       CX := Start_Hi;
  473.       DX := Start_Lo;
  474.       MSDOS(Regs);
  475.       Release_Phys_Rec := (AL = 0);  { $FF = invalid record }
  476.     end;
  477. end; { function Release_Phys_Rec }
  478.  
  479. function Clear_Phys_Rec(Handle, Start_Hi, Start_Lo : integer): boolean;
  480. { Handle is the file handle, Start_Hi and Start_Lo are the boundaries }
  481. { of the file region to be locked. Clearing a record will unlock it }
  482. { and remove it from the log table. }
  483. begin
  484.   with regs do
  485.     begin
  486.       AH := $BE;
  487.       BX := Handle;
  488.       CX := Start_Hi;
  489.       DX := Start_Lo;
  490.       MSDOS(Regs);
  491.       Clear_Phys_Rec := (AL = 0);
  492.     end;
  493. end; { function Clear_Phys_Rec(Handle, Start_Hi, Start_Lo : integer) }
  494.  
  495. function Lock_Phys_Rec_Set(flgs : byte; Timeout : integer): boolean;
  496. { flgs are the lock flags:  bit 1 set means shared (non-exclusive) lock }
  497. { Timeout is in 1/18 seconds, 0 = no wait, -1 means indefinite wait }
  498. { This function attempts to lock all of the records logged in the station's }
  499. { log table. }
  500. begin
  501.   with regs do
  502.     begin
  503.       AH := $C2;
  504.       AL := flgs;
  505.       BP := TimeOut;
  506.       MSDOS(Regs);
  507.       Lock_Phys_Rec_Set := (AL = 0);    { $FF = fail, $FE = timeout fail }
  508.     end;
  509. end; { function Lock_Phys_Rec_Set(flgs, Timeout : byte) }
  510.  
  511. function Release_Phys_Rec_Set : boolean;
  512. { unlocks the entire record log table of the station.  records remain in }
  513. { the log table. }
  514. begin
  515.   regs.AH := $C3;
  516.   MSDOS(Regs);
  517.   Release_Phys_Rec_Set := (regs.AL = 0);
  518. end; { function Release_Phys_Rec_Set  }
  519.  
  520. function Clear_Phys_Rec_Set : boolean;
  521. { unlocks and removes from the log table any records logged and locked }
  522. begin
  523.   regs.AH := $C4;
  524.   MSDOS(Regs);
  525.   Clear_Phys_Rec_Set := (regs.AL = 0);
  526. end; { function Clear_Phys_Rec_Set  }
  527.  
  528. { Note: Example programs and printing functions will be included in the }
  529. { first revision of this toolbox. }
  530.